package org.ww.product.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.ww.common.constant.ProductConstant;
import org.ww.common.to.SkuFullReductionTo;
import org.ww.common.to.SkuWareStockTo;
import org.ww.common.to.SpuBoundsTo;
import org.ww.common.to.es.SkuEsModel;
import org.ww.common.utils.PageUtils;
import org.ww.common.utils.Query;
import org.ww.common.utils.R;
import org.ww.product.dao.SpuInfoDao;
import org.ww.product.entity.*;
import org.ww.product.feign.CouponFeignService;
import org.ww.product.feign.SearchFeignService;
import org.ww.product.feign.WareFeignService;
import org.ww.product.service.*;
import org.ww.product.vo.*;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service("spuInfoService")
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {

    @Autowired
    private SpuInfoDescService spuInfoDescService;
    @Autowired
    private SpuImagesService spuImagesService;
    @Autowired
    private ProductAttrValueService productAttrValueService;
    @Autowired
    private AttrService attrService;
    @Autowired
    private SkuInfoService skuInfoService;
    @Autowired
    private SkuImagesService skuImagesService;
    @Autowired
    private SkuSaleAttrValueService skuSaleAttrValueService;
    @Autowired
    private CouponFeignService couponFeignService;
    @Autowired
    private BrandService brandService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private WareFeignService wareFeignService;
    @Autowired
    private SearchFeignService searchFeignService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                new QueryWrapper<SpuInfoEntity>()
        );

        return new PageUtils(page);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveSpuInfo(SpuSaveVo vo) {
        //1、保存spu基本信息 pms_spu_info
        SpuInfoEntity spuInfoEntity = new SpuInfoEntity();
        BeanUtils.copyProperties(vo,spuInfoEntity);
        this.save(spuInfoEntity);

        //2、保存spu的描述图片 pms_spu_info_desc
        SpuInfoDescEntity spuInfoDescEntity = new SpuInfoDescEntity();
        spuInfoDescEntity.setSpuId(spuInfoEntity.getId());
        spuInfoDescEntity.setDecript(String.join(",",vo.getDecript()));
        spuInfoDescService.save(spuInfoDescEntity);

        //3、保存spu的图片集 pms_spu_images
        List<SpuImagesEntity> spuImagesEntityList = Optional.ofNullable(vo.getImages())
                .orElseGet(ArrayList::new)
                .stream()
                .map(image -> {
                    SpuImagesEntity spuImagesEntity = new SpuImagesEntity();
                    spuImagesEntity.setSpuId(spuInfoEntity.getId());
                    spuImagesEntity.setImgUrl(image);
                    return spuImagesEntity;
                }).collect(Collectors.toList());
        spuImagesService.saveBatch(spuImagesEntityList);

        //4、保存spu的规格参数 pms_product_attr_value
        List<BaseAttrs> baseAttrs = vo.getBaseAttrs();
        List<Long> attrIds = Optional.ofNullable(baseAttrs)
                .orElseGet(ArrayList::new)
                .stream()
                .map(BaseAttrs::getAttrId)
                .distinct()
                .collect(Collectors.toList());
        List<AttrEntity> attrEntityList = attrService.getByIds(attrIds);

        List<ProductAttrValueEntity> productAttrValueEntities = Optional.ofNullable(baseAttrs)
                .orElseGet(ArrayList::new)
                .stream()
                .map(attr -> {
                    ProductAttrValueEntity productAttrValueEntity = new ProductAttrValueEntity();
                    productAttrValueEntity.setAttrId(attr.getAttrId());
                    productAttrValueEntity.setSpuId(spuInfoEntity.getId());

                    //匹配attrName
                    attrEntityList.stream()
                            .filter(a -> a.getAttrId().equals(attr.getAttrId()))
                            .findFirst()
                            .ifPresent(a -> productAttrValueEntity.setAttrName(a.getAttrName()));

                    productAttrValueEntity.setAttrValue(attr.getAttrValues());
                    productAttrValueEntity.setQuickShow(attr.getShowDesc());
                    return productAttrValueEntity;
                }).collect(Collectors.toList());
        productAttrValueService.saveBatch(productAttrValueEntities);

        //5、保存spu的积分信息 积分服务-> sms_spu_bounds
        SpuBoundsTo spuBoundsTo = new SpuBoundsTo();
        Bounds bounds = vo.getBounds();
        BeanUtils.copyProperties(bounds,spuBoundsTo);
        spuBoundsTo.setSpuId(spuInfoEntity.getId());
        R spuBoundR = couponFeignService.spuBoundsSave(spuBoundsTo);
        if(spuBoundR.getCode() != 0){
            log.error("远程调用spu保存积分信息失败");
        }


        //5、保存当前spu对应的所有sku信息

        List<Skus> skus = vo.getSkus();

        Optional.ofNullable(skus)
                .orElseGet(ArrayList::new)
                .forEach(s -> {
                    String defaultImg = "";
                    for (Images image : s.getImages()) {
                        if(image.getDefaultImg() == 1){
                            defaultImg = image.getImgUrl();
                        }
                    }

                    //5.1、sku的基本信息 pms_sku_info
                    //构造sku基本信息
                    SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
                    BeanUtils.copyProperties(s,skuInfoEntity);
                    skuInfoEntity.setBrandId(spuInfoEntity.getBrandId());
                    skuInfoEntity.setCatalogId(spuInfoEntity.getCatalogId());
                    skuInfoEntity.setSaleCount(0L);
                    skuInfoEntity.setSpuId(spuInfoEntity.getId());
                    skuInfoEntity.setSkuDefaultImg(defaultImg);
                    skuInfoService.save(skuInfoEntity);

                    Long skuId = skuInfoEntity.getSkuId();

                    //5.2、sku的图片信息 pms_spu_images
                    List<Images> images = s.getImages();
                    List<SkuImagesEntity> skuImages = Optional.ofNullable(images)
                            .orElseGet(ArrayList::new)
                            .stream()
                            .map(i -> {
                                SkuImagesEntity skuImagesEntity = new SkuImagesEntity();
                                skuImagesEntity.setSkuId(skuId);
                                skuImagesEntity.setImgUrl(i.getImgUrl());
                                skuImagesEntity.setDefaultImg(i.getDefaultImg());
                                return skuImagesEntity;
                            }).filter(i -> StringUtils.isNotBlank(i.getImgUrl()))
                            .collect(Collectors.toList());
                    skuImagesService.saveBatch(skuImages);

                    //5.3、sku的销售属性信息 pms_sku_sale_attr_value
                    List<Attr> attr = s.getAttr();
                    List<SkuSaleAttrValueEntity> skuSaleAttrValueEntities = Optional.ofNullable(attr)
                            .orElseGet(ArrayList::new)
                            .stream()
                            .map(a -> {
                                SkuSaleAttrValueEntity skuSaleAttrValueEntity = new SkuSaleAttrValueEntity();
                                BeanUtils.copyProperties(a, skuSaleAttrValueEntity);
                                skuSaleAttrValueEntity.setSkuId(skuId);
                                return skuSaleAttrValueEntity;
                            }).collect(Collectors.toList());
                    skuSaleAttrValueService.saveBatch(skuSaleAttrValueEntities);

                    //5.4、sku的优惠满减等信息 积分服务 -> sms_sku_full_reduction/sms_sku_ladder/sms_member_price
                    SkuFullReductionTo skuFullReductionTo = new SkuFullReductionTo();
                    BeanUtils.copyProperties(s,skuFullReductionTo);
                    skuFullReductionTo.setSkuId(skuId);
                    if(skuFullReductionTo.getFullCount() > 0 || skuFullReductionTo.getFullPrice().compareTo(BigDecimal.ZERO) == 1){
                        R fullReductionR = couponFeignService.saveFullReduction(skuFullReductionTo);
                        if(fullReductionR.getCode() != 0){
                            log.error("远程调用sku保存满减优惠信息失败");
                        }
                    }

                });

    }

    @Override
    public PageUtils queryPageByParams(Map<String, Object> params) {
        LambdaQueryWrapper<SpuInfoEntity> wrapper = Wrappers.lambdaQuery();
        String key = (String) params.get("key");
        if(StringUtils.isNotBlank(key)){
            wrapper.and(w -> w.eq(SpuInfoEntity::getId,key).or().like(SpuInfoEntity::getSpuName,key));
        }
        String status = (String) params.get("status");
        if(StringUtils.isNotBlank(status)){
            wrapper.eq(SpuInfoEntity::getPublishStatus,status);
        }
        String brandId = (String) params.get("brandId");
        if(StringUtils.isNotBlank(brandId)){
            wrapper.eq(SpuInfoEntity::getBrandId,brandId);
        }
        String catelogId = (String) params.get("catelogId");
        if(StringUtils.isNotBlank(catelogId)){
            wrapper.eq(SpuInfoEntity::getCatalogId,catelogId);
        }

        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                wrapper
        );

        return new PageUtils(page);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void up(Long spuId) {
        //将sku数据存入es
        List<SkuEsModel> esModels = new ArrayList<>();

        //构造列表数据
        List<SkuInfoEntity> skuInfoEntities = skuInfoService.getBySpuId(spuId);
        List<Long> brandIds = Optional.ofNullable(skuInfoEntities)
                .orElseGet(ArrayList::new)
                .stream()
                .map(SkuInfoEntity::getBrandId)
                .distinct()
                .collect(Collectors.toList());

        List<Long> catalogIds = Optional.ofNullable(skuInfoEntities)
                .orElseGet(ArrayList::new)
                .stream()
                .map(SkuInfoEntity::getCatalogId)
                .distinct()
                .collect(Collectors.toList());

        List<Long> skuIds = Optional.ofNullable(skuInfoEntities)
                .orElseGet(ArrayList::new)
                .stream()
                .map(SkuInfoEntity::getSkuId)
                .distinct()
                .collect(Collectors.toList());

        //查询品牌和分类的名字信息
        List<BrandEntity> brandEntities = brandService.selectByIds(brandIds);
        //查询分类名称
        List<CategoryEntity> categoryEntities = categoryService.getByIds(catalogIds);

        // 4、查询当前sku的所有可以被用来检索的规格属性
        List<ProductAttrValueEntity> productAttrValueEntities = productAttrValueService.getBySpuId(spuId);
        List<Long> attrIds = Optional.ofNullable(productAttrValueEntities)
                .orElseGet(ArrayList::new)
                .stream()
                .map(ProductAttrValueEntity::getAttrId)
                .distinct()
                .collect(Collectors.toList());

        List<Long> searchAttrIds = attrService.selectSearchAttrIds(attrIds);
        List<SkuEsModel.Attr> skuEsAttrs = Optional.ofNullable(productAttrValueEntities)
                .orElseGet(ArrayList::new)
                .stream()
                .filter(item -> searchAttrIds.contains(item.getAttrId()))
                .map(item -> {
                    SkuEsModel.Attr skuEsAttr = new SkuEsModel.Attr();
                    BeanUtils.copyProperties(item, skuEsAttr);
                    return skuEsAttr;
                })
                .collect(Collectors.toList());

        //1、发送远程调用，库存系统查询是否有库存
        Map<Long, Boolean> skuHasStockMap = null;
        try{
            R r = wareFeignService.hasstock(skuIds);
            TypeReference<List<SkuWareStockTo>> typeReference = new TypeReference<List<SkuWareStockTo>>() {
            };
            skuHasStockMap = Optional.ofNullable(r.getData(typeReference))
                    .orElseGet(ArrayList::new)
                    .stream()
                    .collect(Collectors.toMap(SkuWareStockTo::getSkuId, SkuWareStockTo::getIsStock));
        }catch (Exception e){
            log.error("调用远程库存服务失败:{}",e.getMessage());
        }


        Map<Long, Boolean> finalSkuHasStockMap = skuHasStockMap;
        Optional.ofNullable(skuInfoEntities)
                .orElseGet(ArrayList::new)
                .forEach(s -> {
                    SkuEsModel skuEsModel = new SkuEsModel();
                    BeanUtils.copyProperties(s,skuEsModel);

                    skuEsModel.setSkuPrice(s.getPrice());
                    skuEsModel.setSkuImg(s.getSkuDefaultImg());

                    //查询是否有库存
                    if(finalSkuHasStockMap != null){
                        skuEsModel.setHasStock(finalSkuHasStockMap.get(s.getSkuId()));
                    }else{
                        skuEsModel.setHasStock(Boolean.TRUE);
                    }


                    //2、热度评分
                    skuEsModel.setHotScore(0L);

                    //匹配品牌名称
                    Optional.ofNullable(brandEntities)
                            .orElseGet(ArrayList::new)
                            .stream()
                            .filter(b -> b.getBrandId().equals(s.getBrandId()))
                            .findFirst()
                            .ifPresent(b -> {
                                skuEsModel.setBrandName(b.getName());
                                skuEsModel.setBrandImg(b.getLogo());
                            });

                    //匹配分类名称
                    Optional.ofNullable(categoryEntities)
                            .orElseGet(ArrayList::new)
                            .stream()
                            .filter(c -> c.getCatId().equals(s.getCatalogId()))
                            .findFirst()
                            .ifPresent(c -> skuEsModel.setCatalogName(c.getName()));

                    //设置检索属性
                    skuEsModel.setAttrs(skuEsAttrs);

                    esModels.add(skuEsModel);

                });

        //5、将数据发送给es进行保存: gulimall-search;
        R r = searchFeignService.productStatusUp(esModels);
        if(r.getCode() == 0){
            //成功:更改spu状态
            LambdaUpdateWrapper<SpuInfoEntity> updateWrapper = Wrappers.lambdaUpdate();
            updateWrapper.set(SpuInfoEntity::getPublishStatus, ProductConstant.StatusEnum.SPU_ON.getCode());
            updateWrapper.set(SpuInfoEntity::getUpdateTime,new Date());
            updateWrapper.eq(SpuInfoEntity::getId,spuId);
            baseMapper.update(null,updateWrapper);
        }else{
            //远程调用失败
            //TODO：重复调用？接口幂等性;重试机制
        }

    }

    @Override
    public SpuInfoEntity getSpuInfoBySkuId(Long skuId) {
        SkuInfoEntity skuInfoEntity = skuInfoService.getById(skuId);
        SpuInfoEntity spuInfoEntity = baseMapper.selectById(skuInfoEntity.getSpuId());
        return spuInfoEntity;
    }

}